/*******************************************************************************
 * Copyright (c) 2007, Geophysical Center RAS
 * Sergey Berezin, Dmitry Voitsekhovskiy
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms,
 * with or without modification, are permitted provided
 * that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Geophysical Center RAS nor the names
 * of its contributors may be used to endorse or promote products
 * derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
﻿using System;

namespace VisualEsse.DataEngine.Types
{
   
    public struct RangeD
    {
        public double min, max;

        ///
        /// <summary>Constructs range from pair of values</summary>
        /// 
        public RangeD(double x, double y)
        {
            if (x < y)
            {
                min = x;
                max = y;
            }
            else
            {
                min = y;
                max = x;
            }
        }

        ///
        /// <summary>Constructs range from grid min and max coordinates</summary>
        ///
        public RangeD(INonUniformGrid1d grid)
        {
            min = grid.Knots[0];
            max = grid.Knots[grid.Length - 1];
        }

        ///
        /// <summary>Construcs range from min and max values of specified grid</summary>
        /// 
        public RangeD(IScalarArray2d data)
        {
            min = max = data[0, 0];
            for (int i = 0; i < data.Width; i++)
                for (int j = 0; j < data.Height; j++)
                {
                    double temp = data[i, j];
                    if (min > temp)
                        min = temp;
                    if (max < temp)
                        max = temp;
                }
        }

        /*	public RangeD(IGrid2d grid,bool bx) {
                min = max = 0;
                for(int i = 0;i<grid.Width;i++) {
                    if(i == 0) 
                        min = max = (bx)?(grid.GetPoint(0,0).x):(grid.GetPoint(0,0).y);
                    for(int j = 0;j<grid.Height;j++) {
                        double temp = (bx)?(grid.GetPoint(i,j).x):(grid.GetPoint(i,j).y); 
                        if(min > temp)
                            min = temp;
                        if(max < temp)
                            max = temp;
                    }
                }			
            }*/

        /*	public RangeD(IVector2dRectField data) {
                min = max = 0;
                for(int i = 0;i<data.X.Size;i++) {
                    Vector2d[] temp = data.GetColumn(i);
                    if(i == 0)
                        min = max = temp[0].Length;
                    for(int j = 0;j<temp.Length;j++) {
                        double length = temp[j].Length;
                        if(min > length)
                            min = length;
                        if(max < length)
                            max = length;
                    }
                }
            }*/

        public double Length
        {
            get
            {
                return (max - min);
            }
        }

        public double Center
        {
            get
            {
                return (min + max) / 2;
            }
        }

        public void Increase(double delta)
        {
            min -= delta / 2;
            max += delta / 2;
        }

        public double Scale(double x, RangeD dst)
        {
            return dst.min + dst.Length * (x - min) / Length;
        }

        public void Unite(RangeD another)
        {
            if (min > another.min)
                min = another.min;
            if (max < another.max)
                max = another.max;
        }

        public override string ToString()
        {
            return String.Format("[{0},{1}]", min, max);
        }
    }
}
